package transformer

import (
	"fmt"
	"strings"
	"sync"
	"time"

	"github.com/gogf/gf/encoding/gurl"
	"github.com/gogf/gf/text/gstr"

	"go-learn/go_learn/prometheus/web_hook/global"
	"go-learn/go_learn/prometheus/web_hook/model"
	"go-learn/go_learn/prometheus/web_hook/pkg/oss"
)

var alertTml = `
- 告警实例: %v
- 告警状态：%v
- 告警名称: %v
- 告警详情: %v
- 故障时间: %v
- 查看详情: [点击查看](%v)
%v
`

// TransformToMarkdown transform alertmanager notification to dingtalk markdow message
func TransformToMarkdown(notification model.Notification) (data model.NotifyData, err error) {
	loc, _ := time.LoadLocation("Asia/Shanghai")

	alertMap := assembleAlerts(notification)
	ossClient, _ := oss.NewOss(global.Oss)
	ossUrlMap := make(map[string]string)

	// 获取prometheus管理后台图片的oss地址
	wg := sync.WaitGroup{}
	for alertName, v := range alertMap {
		wg.Add(1)

		alertNameTmp := alertName
		_, encodeUrl := HandleUrl(v.Alerts[0].GeneratorURL)
		urlTransferTmp := global.HtmlToImg.Domain + encodeUrl

		go func(wg *sync.WaitGroup) {
			defer wg.Done()
			ossUrl, _ := ossClient.PutObjectWithUrl(urlTransferTmp)
			ossUrlMap[alertNameTmp] = ossUrl
		}(&wg)
	}
	wg.Wait()

	// 获取发送的内容
	for alertName, alertData := range alertMap {
		alertTxt := ""
		desc := buildDesc(alertData.Alerts)
		rawUrl, _ := HandleUrl(alertData.Alerts[0].GeneratorURL)

		alertTxt += fmt.Sprintf(
			alertTml,
			alertData.Instance,
			alertData.Status,
			alertData.RealAlertName,
			desc,
			alertData.Alerts[0].StartsAt.In(loc).Format("15:04:05"),
			rawUrl,
			"![]("+ossUrlMap[alertName]+")",
		)

		tmp := &model.Notify{
			RobotName: alertData.RobotName,
			Title:     alertData.RealAlertName,
			Content:   alertTxt,
		}
		data = append(data, tmp)
	}

	return
}

func assembleAlerts(notification model.Notification) (res model.AlertMap) {
	alerts := notification.Alerts
	res = model.AlertMap{}

	for _, v := range alerts {
		alertname := fmt.Sprintf("%s-%s", v.Labels.Alertname, v.Status)

		if _, ok := res[alertname]; ok {
			alertData := res[alertname]
			alertData.Alerts = append(alertData.Alerts, v)

			res[alertname] = alertData
		} else {
			robotName, realAlertName := handleAlertName(v.Labels.Alertname)
			alertData := model.AlertData{
				Instance:      v.Labels.Instance,
				Status:        v.Status,
				RobotName:     robotName,
				RealAlertName: realAlertName,
				Alerts:        []model.Alert{v},
			}

			res[alertname] = alertData
		}
	}

	return
}

// handleAlertName 处理告警名，获取要发到哪个群
func handleAlertName(alertName string) (string, string) {
	alerts := strings.Split(alertName, "|")
	if len(alerts) < 2 {
		return alertName, alertName
	}

	return alerts[0], alerts[1]
}

// buildDesc 获取告警详情内容
func buildDesc(alerts []model.Alert) (desc string) {
	if len(alerts) > 0 {
		desc = alerts[0].Annotations.Description
	}

	var (
		queueName   []string
		requestPath []string
		path        string
	)
	for _, v := range alerts {
		if v.Labels.Queue != "" {
			queueName = append(queueName, v.Labels.Queue)
		}
		if v.Labels.RequestPath != "" {
			if v.Labels.Module != "" {
				path = v.Labels.RequestPath + "module:(" + v.Labels.Module + ")"
			} else {
				path = v.Labels.RequestPath
			}
			requestPath = append(requestPath, path)
		}
	}

	if len(requestPath) > 0 {
		desc += "，接口地址：" + strings.Join(requestPath, "\n")
	}
	if len(queueName) > 0 {
		desc += "，队列名：" + strings.Join(queueName, "\n")
	}
	return
}

func HandleUrl(generatorURL string) (string, string) {
	ret := global.Prometheus.Host + "?" + gstr.StrEx(generatorURL, "?")
	ret = strings.TrimRight(ret, "1")
	ret = ret + "0"
	encodeUrl := gurl.Encode(ret)

	return ret, encodeUrl
}
